﻿using System;
using WikiPlex;
using WikiPlex.Formatting;

namespace WikiMaml.Renderers
{
    /// <summary>
    /// Will render all source code scopes.
    /// </summary>
    public class SourceCodeRenderer : IRenderer
    {
        /// <summary>
        /// Gets the id of a renderer.
        /// </summary>
        public string Id
        {
            get { return "SourceCode"; }
        }

        /// <summary>
        /// Determines if this renderer can expand the given scope name.
        /// </summary>
        /// <param name="scopeName">The scope name to check.</param>
        /// <returns>A boolean value indicating if the renderer can or cannot expand the macro.</returns>
        public bool CanExpand(string scopeName)
        {
            return (scopeName == ScopeName.SingleLineCode
                    || scopeName == ScopeName.MultiLineCode
                    || scopeName == ScopeName.ColorCodeAshx
                    || scopeName == ScopeName.ColorCodeAspxCs
                    || scopeName == ScopeName.ColorCodeAspxVb
                    || scopeName == ScopeName.ColorCodeCpp
                    || scopeName == ScopeName.ColorCodeCSharp
                    || scopeName == ScopeName.ColorCodeHtml
                    || scopeName == ScopeName.ColorCodeJava
                    || scopeName == ScopeName.ColorCodeJavaScript
                    || scopeName == ScopeName.ColorCodeSql
                    || scopeName == ScopeName.ColorCodeVbDotNet
                    || scopeName == ScopeName.ColorCodeXml
                    || scopeName == ScopeName.ColorCodePhp
                    || scopeName == ScopeName.ColorCodeCss
                    || scopeName == ScopeName.ColorCodePowerShell);
        }

        /// <summary>
        /// Will expand the input into the appropriate content based on scope.
        /// </summary>
        /// <param name="scopeName">The scope name.</param>
        /// <param name="input">The input to be expanded.</param>
        /// <param name="htmlEncode">Function that will html encode the output.</param>
        /// <param name="attributeEncode">Function that will html attribute encode the output.</param>
        /// <returns>The expanded content.</returns>
        public string Expand(string scopeName, string input, Func<string, string> htmlEncode, Func<string, string> attributeEncode)
        {
            if (input.EndsWith(Environment.NewLine))
                input = input.Substring(0, input.Length - Environment.NewLine.Length);

            switch (scopeName)
            {
                case ScopeName.SingleLineCode:
                    return string.Format("<codeInline>{0}</codeInline>", htmlEncode(input));
                case ScopeName.ColorCodeAshx:
                case ScopeName.ColorCodeAspxCs:
                case ScopeName.ColorCodeAspxVb:
                case ScopeName.ColorCodeHtml:
                    return ExpandCode("html", input, htmlEncode);
                case ScopeName.ColorCodeCpp:
                    return ExpandCode("cpp", input, htmlEncode);
                case ScopeName.ColorCodeCSharp:
                    return ExpandCode("cs", input, htmlEncode);
                case ScopeName.ColorCodeJava:
                case ScopeName.MultiLineCode:
                case ScopeName.ColorCodePhp:
                case ScopeName.ColorCodeCss:
                    return ExpandCode("none", input, htmlEncode);
                case ScopeName.ColorCodeJavaScript:
                    return ExpandCode("js", input, htmlEncode);
                case ScopeName.ColorCodeSql:
                    return ExpandCode("sql", input, htmlEncode);
                case ScopeName.ColorCodeVbDotNet:
                    return ExpandCode("vbnet", input, htmlEncode);
                case ScopeName.ColorCodeXml:
                    return ExpandCode("xml", input, htmlEncode);
                case ScopeName.ColorCodePowerShell:
                    return ExpandCode("powershell", input, htmlEncode);
                default:
                    return input;
            }
        }

        private static string ExpandCode(string language, string input, Func<string, string> htmlEncode)
        {
            return string.Format("<code language=\"{0}\">{1}</code>", language, htmlEncode(input));
        }
    }
}